package model.pieces;

import java.util.ArrayList;
import java.util.List;
import model.Cell;
import model.Color;
import model.File;
import model.Move;
import model.Rank;
import model.exceptions.InvalidMoveException;

public class Pawn extends Piece
{   
    private boolean wasLastMoveTwoStepsAhead;
    
    public Pawn(Color color)
    {
        super(color);
        wasLastMoveTwoStepsAhead = false;
    }

    @Override
    public Move moveTo(File file, int rank) throws InvalidMoveException
    {
        int previousRank = getRank();
        Move move = super.moveTo(file, rank);
        wasLastMoveTwoStepsAhead = aheadRank(aheadRank(previousRank)) == rank;
        return move;
    }
    
    @Override
    protected List<Cell> possibleDestinies()
    {
        ArrayList<Cell> possibleDestinies = new ArrayList<Cell>();

        Cell oneStepAhead = getCellFromChessBoard(getFile(), aheadRank(getRank()));
        
        if(oneStepAhead.isEmpty())
        {
            possibleDestinies.add(oneStepAhead);
            
            Cell twoStepsAhead = getCellFromChessBoard(getFile(), aheadRank(aheadRank(getRank())));
            
            if(getRank() == initialRank() && twoStepsAhead.isEmpty())
            {
                possibleDestinies.add(twoStepsAhead);
            }
        }
        
        addDiagonal(getFile().previous(), aheadRank(getRank()), possibleDestinies);
        addDiagonal(getFile().next(), aheadRank(getRank()), possibleDestinies);

        addEnPassant(getFile().next(), aheadRank(getRank()), possibleDestinies());
        addEnPassant(getFile().previous(), aheadRank(getRank()), possibleDestinies());
        
        return possibleDestinies;
    }
    
    private int initialRank()
    {
        return (getColor() == Color.White)? 2 : 7;
    }
    
    private int aheadRank(int rank)
    {
        return Rank.ahead(rank, getColor());
    }

    private void addDiagonal(File file, int rank, List<Cell> possibleDestinies)
    {
        Cell diagonal = getCellFromChessBoard(file, rank);
        
        if(hasAnEnemy(diagonal))
        {
            possibleDestinies.add(diagonal);
        }
    }
    
    private void addEnPassant(File file, int rank, List<Cell> possibleDestinies)
    {
        Cell enPassant = getCellFromChessBoard(file, getRank());
        Cell enPassantDestiny = getCellFromChessBoard(file, rank);
        
        if(hasAnEnemyPawn(enPassant) && enemyPawnLastMoveWasTwoStepsAhead(enPassant) && enPassantDestiny.isEmpty())
        {
            possibleDestinies.add(enPassantDestiny);
        }
    }
    
    private boolean hasAnEnemy(Cell cell)
    {
        return !cell.isEmpty() && cell.getPiece().getColor() == getEnemyColor();
    }
    
    private boolean hasAnEnemyPawn(Cell cell)
    {
        return hasAnEnemy(cell) && cell.getPiece().getClass() == Pawn.class;
    }
    
    private boolean enemyPawnLastMoveWasTwoStepsAhead(Cell cell)
    {
        return ((Pawn) cell.getPiece()).wasLastMoveTwoStepsAhead();
    }
    
    private boolean wasLastMoveTwoStepsAhead()
    {
        return wasLastMoveTwoStepsAhead;
    }
}
